/*
 * File     : X86_64_Unix.s
 * Created  : 21 Apr 2011
 *
 * Copyright © 2011 Matthew Wilson (mj. {my-surname} .uk {at} gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

.intel_syntax
.text


////////////////////////////////////////////////////////////////////////////////
// Call for <=3 int arguments, any number of float arguments                  //
////////////////////////////////////////////////////////////////////////////////


.globl dni_x86_64_unix_call_int_3
    .type dni_x86_64_unix_call_int_3, @function

dni_x86_64_unix_call_int_3:
    // Java JNI signature is:
    //   long      fnptr
    //   long      iarg0
    //   long      iarg1
    //   long      iarg2
    //   double    farg[0..]  // optional
    //
    // Registers:
    //   rdi:      JNIEnv*
    //   rsi:      jclass
    //   rdx:      fnptr
    //   rcx:      iarg0
    //   r8:       iarg1
    //   r9:       iarg2
    //   xmm0..7:  farg0..7
    //
    // Stack:
    //   rsp+8:    (actual spill)

    // preserve fnptr
    movq      %r10, %rdx

    // move displaced arguments
    mov       %rdi, %rcx
    mov       %rsi, %r8
    mov       %rdx, %r9

    jmp       %r10


////////////////////////////////////////////////////////////////////////////////
// Call for 4 int arguments, any number of float arguments                    //
////////////////////////////////////////////////////////////////////////////////

.globl dni_x86_64_unix_call_int_4
    .type dni_x86_64_unix_call_int_4, @function

dni_x86_64_unix_call_int_4:
    // Java JNI signature is:
    //   long      fnptr
    //   int       offset
    //   long      iarg0
    //   long      iarg1
    //   double    farg[0..]  // optional
    //   long      iarg2      // on stack
    //   long      iarg3      // on stack
    //
    // Registers:
    //   rdi:       JNIEnv*
    //   rsi:       jclass
    //   rdx:       fnptr
    //   rcx:       offset
    //   r8:        iarg0
    //   r9:        iarg1
    //   xmm0..7:   farg0..7
    //
    // Stack:
    //   rsp+8:       (actual spill)
    //   rsp+ecx+ 0:  iarg2
    //   rsp+ecx+ 8:  iarg3


    // preserve fnptr
    movq      %r10, %rdx

    // move displaced items
    movq      %rdi, %r8
    movq      %rsi, %r9

    // move forced spill items into registers
    add       %rcx, %rsp
    movq      %rdx, [ %rcx +  0 ]
    movq      %rcx, [ %rcx +  8 ]

    jmp       %r10


////////////////////////////////////////////////////////////////////////////////
// Call for 5 int arguments, any number of float arguments                    //
////////////////////////////////////////////////////////////////////////////////

.globl dni_x86_64_unix_call_int_5
    .type dni_x86_64_unix_call_int_5, @function

dni_x86_64_unix_call_int_5:
    // Java JNI signature is:
    //   long      fnptr
    //   int       offset
    //   long      iarg4
    //   long      iarg0
    //   double    farg[0..]  // optional
    //   long      iarg1      // on stack
    //   long      iarg2      // on stack
    //   long      iarg3      // on stack
    //
    // Registers:
    //   rdi:       JNIEnv*
    //   rsi:       jclass
    //   rdx:       fnptr
    //   rcx:       offset
    //   r8:        iarg4  (ALREADY CORRECT)
    //   r9:        iarg0
    //   xmm0..7:   farg0..7
    //
    // Stack:
    //   rsp+8:       (actual spill)
    //   rsp+ecx+ 0:  iarg1
    //   rsp+ecx+ 8:  iarg2
    //   rsp+ecx+16:  iarg3


    // preserve fnptr
    movq      %r10, %rdx

    // move displaced items
    movq      %rdi, %r9

    // move forced spill items into registers
    add       %rcx, %rsp
    movq      %rsi, [ %rcx +  0 ]
    movq      %rdx, [ %rcx +  8 ]
    movq      %rcx, [ %rcx + 16 ]

    jmp       %r10


////////////////////////////////////////////////////////////////////////////////
// Call for >=6 int arguments, any number of float arguments                  //
////////////////////////////////////////////////////////////////////////////////

.globl dni_x86_64_unix_call_int_6
    .type dni_x86_64_unix_call_int_6, @function

dni_x86_64_unix_call_int_6:
    // Java JNI signature is:
    //   long      fnptr
    //   int       offset
    //   long      iarg4
    //   long      iarg5
    //   double    farg[0..]  // optional
    //   long      iarg[6..]  // optional
    //   long      iarg0      // on stack
    //   long      iarg1      // on stack
    //   long      iarg2      // on stack
    //   long      iarg3      // on stack
    //
    // Registers:
    //   rdi:       JNIEnv*
    //   rsi:       jclass
    //   rdx:       fnptr
    //   rcx:       offset
    //   r8:        iarg4  (ALREADY CORRECT)
    //   r9:        iarg5  (ALREADY CORRECT)
    //   xmm0..7:   farg0..7
    //
    // Stack:
    //   rsp+8:       (actual spill)
    //   rsp+ecx+ 0:  iarg0
    //   rsp+ecx+ 8:  iarg1
    //   rsp+ecx+12:  iarg1
    //   rsp+ecx+16:  iarg1


    // preserve fnptr
    movq      %r10, %rdx

    // move forced spill items into registers
    add       %rcx, %rsp
    movq      %rdi, [ %rcx +  0 ]
    movq      %rsi, [ %rcx +  8 ]
    movq      %rdx, [ %rcx + 16 ]
    movq      %rcx, [ %rcx + 24 ]

    jmp       %r10
